#include <windows.h>
#include <map>
#include "platinum.h"

namespace Platinum{
	namespace Thread{
        std::map< DWORD, HANDLE > g_handlemap;
				
		DWORD WINAPI DummyRun( void* p_data )
		{
			// convert the dummy data
			DummyData* data = (DummyData*)p_data;
			
			// run the function with the given data
			data->m_func( data->m_data );
			
			// now delete the data
			delete data;
			
			// and return 0.
			return 0;
		}
		
		inline ThreadID Create(TFunc p_func, void* p_param )
		{
			ThreadID t;
			// create a new dummy data block
			DummyData* data = new DummyData;
			data->m_func = p_func;
			data->m_data = p_param;
			
				HANDLE h = CreateThread( NULL, 0, DummyRun, data, 0, &t );
				if( h != 0 ) {
					// insert the handle into the handlemap
					g_handlemap[t] = h;
				}
			
			if( t == 0 ) {
				// delete the data first
				delete data;
				// throw an error
				throw Platinum::Error(666,"Thread Creation Failure!" );
			}
				return t;
		}
		
		inline ThreadID GetID() 
		{
			return GetCurrentThreadId();
		}
		
		inline void WaitForFinish( ThreadID p_thread ) 
		{
			// look up the handle and wait for the thread to finish
			WaitForSingleObject( g_handlemap[p_thread], INFINITE );
			// close the handle of the thread
			CloseHandle( g_handlemap[p_thread] );
			// remove the handle from the map
			g_handlemap.erase( p_thread );
		}
		
		inline void Kill( ThreadID& p_thread ) 
		{
			// terminate the thread
			TerminateThread( g_handlemap[p_thread], 0 );
			// close the handle of the thread
			CloseHandle( g_handlemap[p_thread] );
			// remove the handle from the map
			g_handlemap.erase( p_thread );
		}
	
		Mutex::Mutex()
		{
			// we use critical sections in Windows
			InitializeCriticalSection( &m_mutex );
		}
			
		Mutex::~Mutex() 
		{
			DeleteCriticalSection( &m_mutex );
		}
	}
}
